package com.seven.micro_service.tools;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import com.alibaba.fastjson.JSONObject;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;


public class JwtUtil {
    // token秘钥用于签名  太短会报错
    private String SECRET = "qwerasdfdxzvdfajjlkjeiojznvxndjkfaowijeiodl";

    /**
     * 生成Jwt的方法
     *
     * @param id
     *            用户ID
     * @param subject
     *            用户昵称
     * @param ttlMillis
     *            过期时间
     * @return Token String 凭证
     */
    public String createJWT(String id, String subject, long ttlMillis) {
        // 签名方法 HS256
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成Jwt的时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 生成秘钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        // 设置JWT所存储的信息
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm, signingKey);

        //builder.claim("name", "value"); //存储自定义信息

        // 设置过期时间
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }

        // 构建JWT并将其序列化为紧凑的URL安全字符串
        return builder.compact();
    }


    /**
     * 解析JWT
     *
     * @param jwtStr jwt字符串
     * @return JOSNObject 解析结果<br/>
     *         &emsp;&emsp;Success 成功标识<br/>
     *         &emsp;&emsp;&emsp;&emsp;true：成功<br/>
     *         &emsp;&emsp;&emsp;&emsp;false：失败<br/>
     *         &emsp;&emsp;Claim 声明对象<br/>
     *         &emsp;&emsp;ErrCode 错误码<br/>
     *         &emsp;&emsp;&emsp;&emsp;1005：过期<br/>
     *         &emsp;&emsp;&emsp;&emsp;1004：未登录
     */
    public JSONObject parseJWT(String jwtStr) {
        JSONObject pojo = new JSONObject();
        Claims claims;
        try {
            //如果它不是签名的JWS（如预期的那样），则该行将抛出异常
            claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET))
                    .parseClaimsJws(jwtStr)
                    .getBody();
            pojo.put("Success", true);
            pojo.put("Claims", claims);
        } catch (ExpiredJwtException e) {//jwt过期
            pojo.put("Success", false);
            pojo.put("ErrCode", 1005);
            e.printStackTrace();
        } catch (Exception e) {//签名错误，认证失败，视为未登录
            pojo.put("Success", false);
            pojo.put("ErrCode", 1004);
            e.printStackTrace();
        }
        return pojo;
    }
}

